/* $Id: CreateTournamentPanel.java 39 2009-07-24 22:48:06Z h_m_r@gmx.de $ */
package org.jugger.tournament.gui.view;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.jugger.tournament.model.Team;
import org.jugger.tournament.model.Tournament;
import org.jugger.tournament.model.ranking.RankingComparator;
import org.jugger.tournament.model.score.ScoreCalculator;

import util.GUIUtils;
import util.I18N;

/**
 * @author Sven Hamer
 */
public class CreateTournamentPanel extends JPanel {

	private static final long serialVersionUID = 8723830570476753870L;

	private JButton addTeamButton;
	private JButton editTeamButton;
	private JButton removeTeamButton;
	private JButton removeAllTeamsButton;
	private JButton createTournamentButton;
	private JButton abortButton;
	private TeamsTable teamsTable;

	private ArrayList<Team> teams;
	private ScoreCalculator scoreCalculator;
	private RankingComparator rankingComparator;

	private ArrayList<CreateTournamentListener> createTournamentListeners = new ArrayList<CreateTournamentListener>();

	public CreateTournamentPanel(RankingComparator rankingComparator,
			ScoreCalculator scoreCalculator, Collection<Team> teams) {
		setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

		this.teams = new ArrayList<Team>();
		if (teams != null)
			this.teams.addAll(teams);
		this.scoreCalculator = scoreCalculator;
		this.rankingComparator = rankingComparator;

		addTeamButton = new JButton(I18N.__("add"));
		editTeamButton = new JButton(I18N.__("edit"));
		removeTeamButton = new JButton(I18N.__("remove"));
		removeAllTeamsButton = new JButton(I18N.__("removeAll"));
		createTournamentButton = new JButton(I18N.__("createTournament"));
		abortButton = new JButton(I18N.__("abort"));

		addTeamButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				executeAddTeam();
			}
		});
		removeTeamButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				executeRemoveTeam();
			}
		});
		editTeamButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				executeEditTeam();
			}
		});
		removeAllTeamsButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				executeRemoveAllTeams();
			}
		});
		createTournamentButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				executeCreateTournament();
			}
		});
		abortButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				executeAbort();
			}
		});

		reloadData();
	}

	public CreateTournamentPanel() {
		this(null, null, null);
	}

	public void addCreateTournamentListener(CreateTournamentListener l) {
		createTournamentListeners.add(l);
	}

	private void updateGUIElements() {
		removeTeamButton.setEnabled(teamsTable.getSelectedRow() != -1);
		editTeamButton.setEnabled(teamsTable.getSelectedRow() != -1);
		removeAllTeamsButton.setEnabled(teams.size() > 0);
		createTournamentButton.setEnabled(teams.size() > 0);
	}

	private void executeAddTeam() {
		Team newTeam = null;
		boolean added = false;

		do {
			newTeam = EditTeamDialog.showDialog(newTeam, CreateTournamentPanel.this, CreateTournamentPanel.this);

			if (newTeam != null && !teams.contains(newTeam)) {
				teams.add(newTeam);
				teamsTable.reloadData(teams);
				selectLastTeam();

				added = true;
			}

		} while(newTeam != null && !added);
	}

	private void executeEditTeam() {
		int row = teamsTable.getSelectedRow();
		if(row != -1) {
			Team oldTeam = teams.remove(row);
			Team changedTeam = oldTeam;

			boolean changed = false;
			do {
				changedTeam = EditTeamDialog.showDialog(changedTeam, CreateTournamentPanel.this, CreateTournamentPanel.this);

				if (changedTeam != null && !teams.contains(changedTeam)) {
					teams.add(row, changedTeam);
					teamsTable.reloadData(teams);

					// TODO: selektiere die alten daten
					selectLastTeam();

					changed = true;
				}

				if(changedTeam == null) {
					teams.add(row, oldTeam);
				}

			} while(changedTeam != null && !changed);
		}
	}

	private void selectLastTeam() {
		if (teams.size() > 0)
			teamsTable.getSelectionModel().setSelectionInterval(
					teams.size() - 1, teams.size() - 1);
		updateGUIElements();
	}

	private void executeRemoveTeam() {
		int[] indices = teamsTable.getSelectedRows();
		int firstIndex = teamsTable.getSelectedRow();
		int counter = 0;
		for (int index : indices) {
			teams.remove(index - counter);
			++counter;
		}
		teamsTable.reloadData(teams);
		// new selection index
		firstIndex = Math.max(0, Math.min(teams.size() - 1, firstIndex));
		if (firstIndex < teams.size()) {
			teamsTable.getSelectionModel().setSelectionInterval(firstIndex,
					firstIndex);
		}
		updateGUIElements();
	}

	private void executeRemoveAllTeams() {
		teams.clear();
		teamsTable.reloadData(teams);
		updateGUIElements();
	}

	private void executeSelectTeam() {
		updateGUIElements();
	}
	private boolean confirmMixTeam() {
		//Custom button text
		Object[] options = {I18N.__("dialogYes"),
		                    I18N.__("dialogNo")};
		return JOptionPane.YES_OPTION == JOptionPane.showOptionDialog(
				this,
				I18N.__("dialogTextOddTeamQuantity"),
			    I18N.__("dialogTitleOddTeamQuantity"),
			    JOptionPane.YES_NO_OPTION,
			    JOptionPane.QUESTION_MESSAGE,
			    null,
			    options,
			    options[1]
			);
	}
	private void executeCreateTournament() {
		HashSet<Team> teamSet = new HashSet<Team>(teams);
		if(teamSet.size() % 2 == 1) {
			if(!confirmMixTeam()) {
				return;
			}
			teamSet.add( new Team(I18N.__("additionalTeamName"), I18N.__("additionalTeamCity"), true));
		}
		Tournament tournament = new Tournament(rankingComparator,
				scoreCalculator, teamSet);
		for (CreateTournamentListener l : createTournamentListeners) {
			l.performTournamentCreated(tournament);
		}
	}
	private void executeAbort() {
		for (CreateTournamentListener l : createTournamentListeners) {
			l.performAbort();
		}
	}

	public void reloadData() {
		this.removeAll();
		JPanel contentPane = GUIUtils.createYBoxLayoutPanel();

		// TEAMS
		JPanel teamsTablePanel = GUIUtils.createTitledPanelY(I18N.__("teams"));
		teamsTable = new TeamsTable(teams);
		teamsTable.getSelectionModel().addListSelectionListener(
				new ListSelectionListener() {
					public void valueChanged(ListSelectionEvent e) {
						executeSelectTeam();
					}
				});
		teamsTable.addMouseListener(new MouseListener() {
			public void mouseClicked(MouseEvent arg0) {
				if(arg0.getClickCount() > 1) {
					executeEditTeam();
				}
			}
			public void mouseEntered(MouseEvent arg0) {
			}
			public void mouseExited(MouseEvent arg0) {
			}
			public void mousePressed(MouseEvent arg0) {
			}
			public void mouseReleased(MouseEvent arg0) {
			}
		});

		JPanel newTeamPanel = GUIUtils.createXBoxLayoutPanel();
		newTeamPanel.add(addTeamButton);
		newTeamPanel.add(editTeamButton);
		newTeamPanel.setMaximumSize(new Dimension(500, (int) addTeamButton
				.getPreferredSize().getHeight()));
		newTeamPanel.setPreferredSize(newTeamPanel.getMaximumSize());
		JPanel subTeamTablePanel = GUIUtils.createXBoxLayoutPanel();
		subTeamTablePanel.add(newTeamPanel);
		subTeamTablePanel.add(Box.createHorizontalGlue());
		subTeamTablePanel.add(removeTeamButton);
		subTeamTablePanel.add(removeAllTeamsButton);
		teamsTablePanel.add(new JScrollPane(teamsTable));
		teamsTablePanel.add(subTeamTablePanel);

		// TOURNAMENT TYPE
		JPanel tournamentSettingsPanel = GUIUtils.createTitledPanelY(I18N
				.__("tournamentSettings"));
		JPanel tournamentSubPanel = GUIUtils.createXBoxLayoutPanel();
		tournamentSubPanel.add(GUIUtils.createFixedWidthLabel(I18N
				.__("rankingCalculation")
				+ ":", 400));

		JComboBox rankingComparatorComboBox = new JComboBox();
		for(RankingComparator rC: RankingComparator.getAll()) {
			rankingComparatorComboBox.addItem(rC);
		}
		rankingComparatorComboBox.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				if(e.getStateChange() == ItemEvent.SELECTED) {
					rankingComparator = (RankingComparator)e.getItem();
				}
			}
		});
		if(rankingComparator == null) {
			rankingComparator = (RankingComparator)rankingComparatorComboBox.getSelectedItem();
		}
		else {
			rankingComparatorComboBox.setSelectedItem(rankingComparator);
		}

		rankingComparatorComboBox.setMinimumSize(new Dimension(500,
				(int) addTeamButton.getPreferredSize().getHeight()));
		rankingComparatorComboBox.setMaximumSize(new Dimension(500,
				(int) addTeamButton.getPreferredSize().getHeight()));
		tournamentSubPanel.add(Box.createHorizontalGlue());
		tournamentSubPanel.add(rankingComparatorComboBox);
		tournamentSettingsPanel.add(tournamentSubPanel);

		tournamentSubPanel = GUIUtils.createXBoxLayoutPanel();
		tournamentSubPanel.add(GUIUtils.createFixedWidthLabel(I18N
				.__("scoreCalculation")
				+ ":", 400));

		JComboBox scoreCalculatorComboBox = new JComboBox();
		for(ScoreCalculator sC: ScoreCalculator.getAll()) {
			scoreCalculatorComboBox.addItem(sC);
		}
		scoreCalculatorComboBox.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				if(e.getStateChange() == ItemEvent.SELECTED) {
					scoreCalculator = (ScoreCalculator) e.getItem();
				}
			}
		});
		if(scoreCalculator == null) {
			scoreCalculator = (ScoreCalculator)scoreCalculatorComboBox.getSelectedItem();
		}
		else {
			scoreCalculatorComboBox.setSelectedItem(scoreCalculator);
		}

		scoreCalculatorComboBox.setMinimumSize(new Dimension(500,
				(int) addTeamButton.getPreferredSize().getHeight()));
		scoreCalculatorComboBox.setMaximumSize(new Dimension(500,
				(int) addTeamButton.getPreferredSize().getHeight()));
		tournamentSubPanel.add(Box.createHorizontalGlue());
		tournamentSubPanel.add(scoreCalculatorComboBox);
		tournamentSettingsPanel.add(tournamentSubPanel);

		JPanel createButtonPanel = GUIUtils.createXBoxLayoutPanel();
		createButtonPanel.add(Box.createHorizontalGlue());
		createButtonPanel.add(createTournamentButton);
		createButtonPanel.add(abortButton);

		contentPane.add(tournamentSettingsPanel);
		contentPane.add(teamsTablePanel);
		contentPane.add(Box.createVerticalStrut(10));
		contentPane.add(createButtonPanel);
		contentPane.add(Box.createVerticalGlue());
		add(contentPane);

		selectLastTeam();
	}

	public interface CreateTournamentListener {
		public void performTournamentCreated(Tournament tournament);
		public void performAbort();
	}
}
